package com.sunwayhorizo.health.business.patad.integration;

import java.util.ArrayList;
import java.util.List;

import javax.ejb.Stateless;

import org.jboss.seam.Component;
import org.jboss.seam.annotations.Name;

import com.sunwayhorizo.health.business.base.BaseManager;
import com.sunwayhorizo.health.business.clinic.mqa.QADefectManagerLocal;
import com.sunwayhorizo.health.business.dto.PageDTO;
import com.sunwayhorizo.health.business.dto.ResultsDTO;
import com.sunwayhorizo.health.business.dto.clinic.mqa.DefectInfoDTO;
import com.sunwayhorizo.health.business.dto.patad.encounter.PatientEncounterDTO;
import com.sunwayhorizo.health.business.patad.encounter.AdmitManagerLocal;
import com.sunwayhorizo.health.business.patad.encounter.ReceivingManagerLocal;
import com.sunwayhorizo.health.business.patad.encounter.query.PatientEncounterQueryLocal;
import com.sunwayhorizo.health.business.patad.integration.query.PatientQualityControlQueryLocal;
import com.sunwayhorizo.health.common.DataTypeUtil;
import com.sunwayhorizo.health.common.Hl7NullRemover;
import com.sunwayhorizo.health.common.ListUtil;
import com.sunwayhorizo.health.common.StrUtil;
import com.sunwayhorizo.health.hl7.common.Hl7Exception;
import com.sunwayhorizo.health.hl7.rim.ActParticipation;
import com.sunwayhorizo.health.hl7.rim.PatientEncounter;
import com.sunwayhorizo.health.hl7.vocabulary.ActCdSetCode;
import com.sunwayhorizo.health.hl7.vocabulary.ActCode;
import com.sunwayhorizo.health.hl7.vocabulary.ActIICode;
import com.sunwayhorizo.health.hl7.vocabulary.ParticipationType;
import com.sunwayhorizo.health.hl7.vocabulary.RoleCode;

@Name("PatientQualityControlManager")
@Stateless
public class PatientQualityControlManager extends BaseManager implements PatientQualityControlManagerLocal
{
    private PatientQualityControlQueryLocal patientQualityControlQuery = (PatientQualityControlQueryLocal) Component
        .getInstance("PatientQualityControlQuery");
    private QADefectManagerLocal qADefectManager = (QADefectManagerLocal) Component.getInstance("QADefectManager");
    private ReceivingManagerLocal receivingManager = (ReceivingManagerLocal) Component.getInstance("ReceivingManager");
    private PatientEncounterQueryLocal patientEncounterQuery = (PatientEncounterQueryLocal) Component.getInstance("PatientEncounterQuery");
    private AdmitManagerLocal admitManager = (AdmitManagerLocal) Component.getInstance("AdmitManager");

    public ResultsDTO updatePatientTrackFlag(String actId, String trackFlag) throws Hl7Exception
    {
        if (StrUtil.isAllEmpty(actId, trackFlag))
        {
            return this.getResultsDTO("动作id和跟踪状态不能为空", true, null);
        }

        PatientEncounter pe = patientQualityControlQuery.findPatientEncounterByActId(actId);
        if (pe == null)
        {
            return this.getResultsDTO("根据actId找不到对应的Act", true, null);
        }
        if (StrUtil.isNotEmpty(trackFlag))
        {
            if (trackFlag.equals("1"))
            {
                pe.setNegationInd(DataTypeUtil.getBL("true"));
            }
            else
            {
                pe.setNegationInd(DataTypeUtil.getBL("false"));
            }
        }
        em.merge(pe);
        return this.getResultsDTO("跟踪或取消跟踪成功", true, null);
    }

    @Override
    public ResultsDTO findInPatientListByWorkGroup(String workGroupId, PageDTO pageDTO) throws Hl7Exception
    {
        List<PatientEncounter> patientEncounterList = patientQualityControlQuery.findInPatientByWorkGroupId(workGroupId, pageDTO.getPageNo(),
            pageDTO.getPageSize());
        if (ListUtil.isNotEmpty(patientEncounterList))
        {

            List<PatientEncounterDTO> patEncList = convertInPatientEncounterDTOFromPatientEncounter(patientEncounterList);
            if (ListUtil.isEmpty(patEncList))
            {
                log.info("该工作组下没有在院患者");
                return this.getResultsDTO("该工作组下没有在院患者", true, null);

            }
            int total = patientQualityControlQuery.findCountInPatientByWorkGroupId(workGroupId).intValue();
            pageDTO.setTotalRecord(total);
            log.info("该工作组下有" + total + "个在院");
            return this.getResultsDTO("该工作组下有" + total + "个在院患者", true, patEncList, pageDTO);
        }
        return this.getResultsDTO("查询在院患者成功", true, null);
    }
    
    @Override
    public ResultsDTO findInPatientListByWorkGroup(String workGroupId) throws Hl7Exception
    {
        List<PatientEncounter> patientEncounterList = patientQualityControlQuery.findInPatientByWorkGroupId(workGroupId,0,0);
        if (ListUtil.isNotEmpty(patientEncounterList))
        {
            List<PatientEncounterDTO> patEncList = convertInPatientEncounterDTOFromPatientEncounter(patientEncounterList);
            if (ListUtil.isEmpty(patEncList))
            {
                log.info("该工作组下没有在院患者");
                return this.getResultsDTO("该工作组下没有在院患者", true, null);

            }
            return this.getResultsDTO("查询在院患者成功", true, patEncList);
        }
        return this.getResultsDTO("查询在院患者成功", true, null);
    }

    public ResultsDTO findInPatientListByWorkGroupAndCritical(String workGroupId, PageDTO pageDTO) throws Hl7Exception
    {
        List<PatientEncounter> patientEncounterList = patientQualityControlQuery.findInPatientByWorkGroupIdByCond(workGroupId,
            ActCdSetCode.CRITICALCODE.toString(), null, null, pageDTO.getPageNo(), pageDTO.getPageSize());
        if (ListUtil.isNotEmpty(patientEncounterList))
        {
            List<PatientEncounterDTO> patEncList = convertInPatientEncounterDTOFromPatientEncounter(patientEncounterList);
            if (ListUtil.isEmpty(patEncList))
            {
                log.info("该工作组下无危重患者");
                return this.getResultsDTO("该工作组下无危重患者", true, null);

            }
            int total = patientQualityControlQuery.findCountInPatientByWorkGroupIdByCond(workGroupId, ActCdSetCode.CRITICALCODE.toString(), null, null)
                .intValue();

            pageDTO.setTotalRecord(total);
            log.info("该工作组下有" + total + "个危重患者");
            return this.getResultsDTO("该工作组下有" + total + "个危重患者", true, patEncList, pageDTO);
        }
        return this.getResultsDTO("查询危重患者成功", true, null);
    }

    public ResultsDTO findInPatientListByWorkGroupAndSurgery(String workGroupId, PageDTO pageDTO) throws Hl7Exception
    {
        List<PatientEncounter> patientEncounterList = patientQualityControlQuery.findInPatientByWorkGroupIdByCond(workGroupId, null,
            ActCdSetCode.SURGERYCODE.toString(), null, pageDTO.getPageNo(), pageDTO.getPageSize());
        if (ListUtil.isNotEmpty(patientEncounterList))
        {
            List<PatientEncounterDTO> patEncList = convertInPatientEncounterDTOFromPatientEncounter(patientEncounterList);
            if (ListUtil.isEmpty(patEncList))
            {
                log.info("该工作组下无手术患者");
                return this.getResultsDTO("该工作组下无手术患者", true, null);

            }
            int total = patientQualityControlQuery.findCountInPatientByWorkGroupIdByCond(workGroupId, null, ActCdSetCode.SURGERYCODE.toString(), null)
                .intValue();
            pageDTO.setTotalRecord(total);
            log.info("该工作组下有" + total + "个手术患者");
            return this.getResultsDTO("该工作组下有" + total + "个手术患者", true, patEncList, pageDTO);
        }
        return this.getResultsDTO("查询手术患者成功", true, null);
    }

    public ResultsDTO findInPatientListByWorkGroupAndTransfuse(String workGroupId, PageDTO pageDTO) throws Hl7Exception
    {
        List<PatientEncounter> patientEncounterList = patientQualityControlQuery.findInPatientByWorkGroupIdByCond(workGroupId, null, null,
            ActCdSetCode.TRANSFUSECODE.toString(), pageDTO.getPageNo(), pageDTO.getPageSize());
        if (ListUtil.isNotEmpty(patientEncounterList))
        {
            List<PatientEncounterDTO> patEncList = convertInPatientEncounterDTOFromPatientEncounter(patientEncounterList);
            if (ListUtil.isEmpty(patEncList))
            {
                log.info("该工作组下无输血患者");
                return this.getResultsDTO("该工作组下无输血患者", true, null);

            }
            int total = patientQualityControlQuery.findCountInPatientByWorkGroupIdByCond(workGroupId, null, null, ActCdSetCode.TRANSFUSECODE.toString())
                .intValue();
            pageDTO.setTotalRecord(total);
            log.info("该工作组下有" + total + "个输血患者");
            return this.getResultsDTO("该工作组下有" + total + "个输血患者", true, patEncList, pageDTO);
        }
        return this.getResultsDTO("查询输血患者成功", true, null);
    }

    public ResultsDTO findOutPatientListByWorkGroupAndLeaveHospital(String workGroupId, String leaveHospitalCode, String startTime, String endTime,
        PageDTO pageDTO) throws Hl7Exception
    {
        List<PatientEncounter> patientEncounterList = patientQualityControlQuery.findOutPatientByWorkGroupIdByCond(workGroupId,
            ActCdSetCode.PELEAVEHOSPITALWAYCDSETCODE.toString(), leaveHospitalCode, startTime, endTime, pageDTO.getPageNo(), pageDTO.getPageSize());
        if (ListUtil.isNotEmpty(patientEncounterList))
        {
            List<PatientEncounterDTO> patEncList = convertOutPatientEncounterDTOFromPatientEncounter(patientEncounterList);
            if (ListUtil.isEmpty(patEncList))
            {
                log.info("该工作组下无出院/死亡患者");
                return this.getResultsDTO("该工作组下无出院/死亡患者", true, null);

            }
            int total = patientQualityControlQuery.findCountOutPatientByWorkGroupIdByCond(workGroupId,
                ActCdSetCode.PELEAVEHOSPITALWAYCDSETCODE.toString(), leaveHospitalCode, startTime, endTime).intValue();
            pageDTO.setTotalRecord(total);
            log.info("该工作组下有" + total + "个出院/死亡患者");
            return this.getResultsDTO("该工作组下有" + total + "个出院/死亡患者", true, patEncList, pageDTO);
        }
        return this.getResultsDTO("查询出院/死亡患者成功", true, null);
    }

    public ResultsDTO findInPatientListByWorkGroupIdAndTrackFlag(String workGroupId, String trackFlag, PageDTO pageDTO) throws Hl7Exception
    {
        List<PatientEncounter> patientEncounterList = patientQualityControlQuery.findInPatientByWorkGroupIdAndTrackFlag(workGroupId, trackFlag,
            pageDTO.getPageNo(), pageDTO.getPageSize());
        if (ListUtil.isNotEmpty(patientEncounterList))
        {
            List<PatientEncounterDTO> patEncList = convertInPatientEncounterDTOFromPatientEncounter(patientEncounterList);
            if (ListUtil.isEmpty(patEncList))
            {
                log.info("该工作组下没有被跟踪的患者");
                return this.getResultsDTO("该工作组下没有被跟踪的患者", true, null);

            }
            int total = patientQualityControlQuery.findCountInPatientByWorkGroupIdAndTrackFlag(workGroupId, trackFlag).intValue();
            pageDTO.setTotalRecord(total);
            log.info("该工作组下有" + total + "个被跟踪的患者");
            return this.getResultsDTO("该工作组下有" + total + "个被跟踪的患者", true, patEncList, pageDTO);
        }
        return this.getResultsDTO("查询在院被跟踪的患者成功", true, null);
    }

    @SuppressWarnings("unchecked")
    @Override
    public ResultsDTO findAllPatientListByWorkGroup(String workGroupId) throws Hl7Exception
    {
        PageDTO dto = new PageDTO();
        dto.setPageNo(0);
        dto.setPageSize(0);
        List<PatientEncounterDTO> allPatientEncounter = new ArrayList<PatientEncounterDTO>();
        ResultsDTO patientInHospital = this.findInPatientListByWorkGroup(workGroupId, dto);
        ResultsDTO patientOutHospital = this.findOutPatientListByWorkGroupAndLeaveHospital(workGroupId, null, null, null, dto);
        List<PatientEncounterDTO> patientEncounterInHospital = (List<PatientEncounterDTO>) patientInHospital.getObject();
        List<PatientEncounterDTO> patientEncounterOutHospital = (List<PatientEncounterDTO>) patientOutHospital.getObject();
        if (ListUtil.isNotEmpty(patientEncounterInHospital))
        {
            allPatientEncounter.addAll(patientEncounterInHospital);
        }
        if (ListUtil.isNotEmpty(patientEncounterOutHospital))
        {
            allPatientEncounter.addAll(patientEncounterOutHospital);
        }
        return this.getResultsDTO("根据工作组查询在院和出院/死亡患者列表成功", true, allPatientEncounter);
    }
    
    @Override
    public ResultsDTO findLastInDepartmentByHosNo(String hosNo) throws Hl7Exception
    {
        PatientEncounter patientEncounter = patientEncounterQuery.findLastIndepartmentByHosNo(hosNo);
        if (patientEncounter!=null)
        {
            PatientEncounterDTO dto = receivingManager.converByIndepartment(patientEncounter);
            // 根据患者角色id拿到患者缺陷信息
            if (dto != null && dto.getPatientBaseInfoDTO() != null && StrUtil.isNotEmpty(dto.getPatientBaseInfoDTO().getPersonId()))
            {
                DefectInfoDTO defectInfo = qADefectManager.findDefectInfoByPatientRoleId(dto.getPatientBaseInfoDTO().getPersonId());
                if (defectInfo != null)
                {
                    dto.setDefectInfoDTO(defectInfo);
                }
            }
            // 就诊号
            String encounterId = patientEncounter.getId(ActIICode.INDEPARTMENT).clinicNo().stringValue();
            // 根据就诊号查询接诊动作
            PatientEncounter receivingAct = patientEncounterQuery.findActiveRecieveingEncounterById(encounterId);
            // 组装接诊三级医生
            receivingManager.convertRecieveEncounter(receivingAct, dto);
            Hl7NullRemover.removeHl7Null(dto);
            return this.getResultsDTO("查询患者成功", true, dto);
        }
        log.info("PatientEncounterQuery-findLastIndepartmentByHosNo-根据病案号查不到"+hosNo+"入科动作");
        return this.getResultsDTO("查询患者失败", true, null);
    }

    private List<PatientEncounterDTO> convertInPatientEncounterDTOFromPatientEncounter(List<PatientEncounter> patientEncounterList) throws Hl7Exception
    {
        List<PatientEncounterDTO> patEncList = new ArrayList<PatientEncounterDTO>();
        for (PatientEncounter encounter : patientEncounterList)
        {
            PatientEncounterDTO dto = receivingManager.converByIndepartment(encounter);
            // 根据患者角色id拿到患者缺陷信息
            if (dto != null && dto.getPatientBaseInfoDTO() != null && StrUtil.isNotEmpty(dto.getPatientBaseInfoDTO().getPersonId()))
            {
                DefectInfoDTO defectInfo = qADefectManager.findDefectInfoByPatientRoleId(dto.getPatientBaseInfoDTO().getPersonId());
                if (defectInfo != null)
                {
                    dto.setDefectInfoDTO(defectInfo);
                }
            }
            if (encounter.getId(ActIICode.INDEPARTMENT) != null && encounter.getId(ActIICode.INDEPARTMENT).clinicNo() != null)
            {
                // 就诊号
                String encounterId = encounter.getId(ActIICode.INDEPARTMENT).clinicNo().stringValue();
                // 根据就诊号查询接诊动作
                PatientEncounter receivingAct = patientEncounterQuery.findActiveRecieveingEncounterById(encounterId);
                // 组装接诊三级医生
                receivingManager.convertRecieveEncounter(receivingAct, dto);
            }
            Hl7NullRemover.removeHl7Null(dto);
            patEncList.add(dto);
        }
        return patEncList;
    }

    private List<PatientEncounterDTO> convertOutPatientEncounterDTOFromPatientEncounter(List<PatientEncounter> patientEncounterList) throws Hl7Exception
    {
        List<PatientEncounterDTO> patEncList = new ArrayList<PatientEncounterDTO>();
        // 出院动作
        for (PatientEncounter encounter : patientEncounterList)
        {
            // 根据出院动作查询入科动作
            PatientEncounterDTO dto = new PatientEncounterDTO();
            String encounterNum = this.getEncounterNumByPatientEncounter(encounter);
            // 就诊号
            String encounterId = encounter.getId(ActIICode.DISCHARGED).clinicNo().stringValue();
            // 根据就诊号查询入科动作
            PatientEncounter inDeaprtAct = patientEncounterQuery.findActByEncounterIdAndNumAndActCode(encounterId,encounterNum,ActCode.INDEPARTMENT.code().stringValue());
            // 组装入科动作
            receivingManager.convertIndepartement(dto, inDeaprtAct);

            // 根据就诊号查询接诊动作
            PatientEncounter receivingAct = patientEncounterQuery.findActByEncounterIdAndNumAndActCode(encounterId,encounterNum,ActCode.RECEIVING.code().stringValue());
            // 组装接诊动作
            receivingManager.convertRecieveEncounter(receivingAct, dto);

            // 根据就诊号查询入院动作
            PatientEncounter inHosAct = patientEncounterQuery.findActByEncounterIdAndNumAndActCode(encounterId,encounterNum,ActCode.HOSPITALIZED.code().stringValue());
            // 组装入院动作
            admitManager.convertPatientEncounterDTO(dto, inHosAct);

            //组装出院信息
            admitManager.convertOutPatientEncounterDTOFromPatientEncounter(encounter, dto);
        
            // 根据患者角色id拿到患者缺陷信息
            if (dto != null && dto.getPatientBaseInfoDTO() != null && StrUtil.isNotEmpty(dto.getPatientBaseInfoDTO().getPersonId()))
            {
                DefectInfoDTO defectInfo = qADefectManager.findDefectInfoByPatientRoleId(dto.getPatientBaseInfoDTO().getPersonId());
                if (defectInfo != null)
                {
                    dto.setDefectInfoDTO(defectInfo);
                }
            }
            Hl7NullRemover.removeHl7Null(dto);
            patEncList.add(dto);
        }
        return patEncList;
    }
    
    private String getEncounterNumByPatientEncounter(PatientEncounter encounter ) throws Hl7Exception{
        if( encounter == null )
        {
            throw new Hl7Exception("住院次数为空,出错");
        }
        for (ActParticipation actPrtcptn : encounter.getParticipations())
        {
            if (actPrtcptn.getTypecode().equals(ParticipationType.SBJ))
            {
                if (actPrtcptn.getRoleparticipation().getCode().code().equals(RoleCode.PATIENT.code()))
                {
                    // 住院次数
                    if (actPrtcptn.getSequenceNumber() != null && actPrtcptn.getSequenceNumber().intValue() != 0)
                    {
                        return actPrtcptn.getSequenceNumber().intValue() +"";

                    }
                    else
                    {
                        return "1";
                    }
                }
            }
        }
        throw new Hl7Exception("住院次数为空,出错");
    }
}
